﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NCM_MSTest.Alg;

namespace NCM_MSTest.Test
{
    [TestClass]
    [TestCategory("非线性方程组数值解测试")]
    public class 非线性方程组数值解测试
    {
        [TestMethod("确定有根区间")]
        public void FindRootIntervalsTest()
        {
            var f = new F(x => Math.Pow(x, 3) + Math.Pow(x, 2) - 3 * x - 3);
            double a = -2, b = 2;
            double[][] intervals;
            NumbericalSolutionOfNonlinearEquations.FindRootIntervals(f, a, b, out intervals);
            Assert.IsTrue(intervals.Length == 3);
            for (int i = 0; i < intervals.Length; i++)
            {
                System.Diagnostics.Trace.WriteLine("[" + intervals[i][0] + "," + intervals[i][1] + "]");
            }
        }
        [TestMethod("二分法")]
        public void 二分法()
        {
            //t^3 + t^2 - 3t -3 = 0
            var f = new F(x => Math.Pow(x, 3) + Math.Pow(x, 2) - 3 * x - 3);
            double a = 1, b = 2;
            double root;
            NumbericalSolutionOfNonlinearEquations.Dichotomy(f, a, b, out root);

            a = -2;
            b = 2;
            double[] roots;
            NumbericalSolutionOfNonlinearEquations.DichotomyEx(f, a, b, out roots);


            Assert.IsTrue(!double.IsNaN(root));
            System.Diagnostics.Trace.WriteLine("Root:" + root);

            Assert.IsTrue(roots.Length > 0);
            for (int i = 0; i < roots.Length; i++)
            {
                System.Diagnostics.Trace.WriteLine($"{i} Root:{roots[i]}");
            }
        }

        [TestMethod("迭代法-代数方程-不动点迭代法、牛顿迭代法")]
        public void 迭代法_求解高次多项式代数方程()
        {
            var f = new F(x => Math.Pow(x, 3) + Math.Pow(x, 2) - 3 * x - 3);
            var g = new F(x => Math.Pow(3 + 3 * x - x * x, 1.0 / 3.0)); //迭代函数
            var df = new F(x => 3 * x * x + 2 * x - 3);//一阶导数
            var t = 2.0;
            var maxN = 100;
            var X = 1.7321;

            double rx1, rx2;
            int n1, n2;

            NumbericalSolutionOfNonlinearEquations.Iteration_FixedPoint(f, g, t, maxN, out rx1, out n1);
            NumbericalSolutionOfNonlinearEquations.Iteration_Newton(f, df, t, maxN, out rx2, out n2);

            Console.WriteLine($"求解高次多项式代数方程：");
            Console.WriteLine($"\t x^3 + x^2 - 3*x -3 = 0");
            Console.WriteLine($"在x=2附近的近似根");
            Console.WriteLine($"标准解：X = {X}");
            Console.WriteLine($"Finxed Point: n={n1} x = {rx1}");
            Console.WriteLine($"Newton      : n={n2} x = {rx2}");

            Assert.IsTrue(X.EqualsDelta(rx1, 1e-4));
            Assert.IsTrue(X.EqualsDelta(rx2, 1e-4));
        }


        [TestMethod("迭代法-代数方程组-不动点迭代法、牛顿迭代法")]
        public void 迭代法_求解方程组()
        {
            var f1 = new FF((x1, x2) => x1 - 0.7 * Math.Sin(x1) - 0.2 * Math.Cos(x2));
            var f2 = new FF((x1, x2) => x2 - 0.7 * Math.Cos(x1) + 0.2 * Math.Sin(x2));

            var g1 = new FF((x1, x2) => 0.7 * Math.Sin(x1) + 0.2 * Math.Cos(x2)); //迭代函数1
            var g2 = new FF((x1, x2) => 0.7 * Math.Cos(x1) - 0.2 * Math.Sin(x2)); //迭代函数2

            var df11 = new FF((x1, x2) => 1 - 0.7 * Math.Cos(x1));  //一阶偏导数
            var df12 = new FF((x1, x2) => 0.2 * Math.Sin(x2));      //一阶偏导数
            var df21 = new FF((x1, x2) => 0.7 * Math.Sin(x1));      //一阶偏导数
            var df22 = new FF((x1, x2) => 1 + 0.2 * Math.Cos(x2));  //一阶偏导数

            var t1 = new double[] { 0.5, 0.5 };
            var t2 = new double[] { 0.5, 0.5 };
            var maxN = 10000;
            var X = new double[] { 0.52632, 0.50798 };

            double[] rx1;
            double[] rx2;
            int n1, n2;

            NumbericalSolutionOfNonlinearEquations.Iteration_FixedPoint(g1, g2, t1, maxN, out rx1, out n1);
            NumbericalSolutionOfNonlinearEquations.Iteration_Newton(f1, f2, df11, df12, df21, df22, t1, maxN, out rx2, out n2);

            Console.WriteLine($"求解高次多项式代数方程：");
            Console.WriteLine($"\t x1 - 0.7*sin(x1) - 0.2*cos(x2) = 0");
            Console.WriteLine($"\t x2 - 0.7*cos(x1) + 0.2*sin(x2) = 0");
            Console.WriteLine($"在(0.5,0.5)附近的近似根");
            Console.WriteLine($"标准解：X1 = {X[0]}  X2 = {X[1]}");
            Console.WriteLine($"Finxed Point: n={n1} x1 = {rx1[0]}  x2 = {rx1[1]}");
            Console.WriteLine($"Newton      : n={n2} x1 = {rx2[0]}  x2 = {rx2[1]}");

            Assert.IsTrue(X[0].EqualsDelta(rx1[0], 1e-4));
            Assert.IsTrue(X[1].EqualsDelta(rx1[1], 1e-4));
        }
    }
}
